﻿using System.Windows.Forms;
using System.Drawing;
using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Collections.Generic;

namespace QExplorer
{
	enum Column
	{
		Name,
		Size,
		Type,
		Attribute,
		ModifiedDate,
		AccessDate,
		CreationDate,
		Count,
	}

	public class QView : ListView
	{
		#region Fields

		private string pwd;
		public string Pwd
		{
			get { return pwd; }
			set { pwd = value; }
		}
		private int sortColIndex;
		private int lastClickTick;
		private Point lastClickPosition;

		private List<string> history = new List<string>();
		private int historyCapacity = 50;
		private int posInHistory = 0;

		private int numFiles;
		private int numFolders;
		private int numHidden;

		public int HistoryCapacity
		{
			get { return historyCapacity; }
			set { historyCapacity = value; }
		}
		public List<string> History
		{
			get
			{
				Debug.WriteLine("History.Count= " + history.Count);
				return history;
			}
			set
			{
				history = value;
			}
		}
		public int PosInHistory
		{
			get { return posInHistory; }
			set
			{
				posInHistory = value;
				Debug.WriteLine("pos= " + PosInHistory);
			}
		}
		private ColumnHeader chName;
		private ColumnHeader chSize;
		private ColumnHeader chType;
		private ColumnHeader chAttribute;
		private ColumnHeader chDateModify;
		private ColumnHeader chDateAccess;
		private ColumnHeader chDateCreate;
		public ContextMenuStrip contextMenu;
		private System.ComponentModel.IContainer components;
		private ToolStripMenuItem refleshToolStripMenuItem;
		private ToolStripMenuItem cutToolStripMenuItem;
		private ToolStripMenuItem copyToolStripMenuItem;
		private ToolStripMenuItem pasteToolStripMenuItem;
		private ToolStripMenuItem newFolderToolStripMenuItem;
		private ToolStripMenuItem deleteToolStripMenuItem;
		private ToolStripMenuItem renameToolStripMenuItem;
		private ToolStripMenuItem newTxtTtoolStripMenuItem;
		private ToolStripSeparator toolStripSeparator1;
		private ToolStripSeparator toolStripSeparator2;
		private ToolStripSeparator toolStripSeparator3;
		private ToolStripSeparator toolStripSeparator4;

		public int SortColIndex
		{
			get { return sortColIndex; }
			set { sortColIndex = value; }
		}
		private QForm form;
		#endregion

		public QView(QForm qform)
			: base()
		{
			InitializeComponent();
			form = qform;
		}

		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(QView));
			this.chName = new System.Windows.Forms.ColumnHeader();
			this.chSize = new System.Windows.Forms.ColumnHeader();
			this.chType = new System.Windows.Forms.ColumnHeader();
			this.chAttribute = new System.Windows.Forms.ColumnHeader();
			this.chDateModify = new System.Windows.Forms.ColumnHeader();
			this.chDateAccess = new System.Windows.Forms.ColumnHeader();
			this.chDateCreate = new System.Windows.Forms.ColumnHeader();
			this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
			this.refleshToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
			this.cutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.pasteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
			this.newFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.newTxtTtoolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
			this.renameToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
			this.deleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.contextMenu.SuspendLayout();
			this.SuspendLayout();
			// 
			// chName
			// 
			resources.ApplyResources(this.chName, "chName");
			// 
			// chSize
			// 
			resources.ApplyResources(this.chSize, "chSize");
			// 
			// chType
			// 
			resources.ApplyResources(this.chType, "chType");
			// 
			// chAttribute
			// 
			resources.ApplyResources(this.chAttribute, "chAttribute");
			// 
			// chDateModify
			// 
			resources.ApplyResources(this.chDateModify, "chDateModify");
			// 
			// chDateAccess
			// 
			resources.ApplyResources(this.chDateAccess, "chDateAccess");
			// 
			// chDateCreate
			// 
			resources.ApplyResources(this.chDateCreate, "chDateCreate");
			// 
			// contextMenu
			// 
			this.contextMenu.AccessibleDescription = null;
			this.contextMenu.AccessibleName = null;
			resources.ApplyResources(this.contextMenu, "contextMenu");
			this.contextMenu.BackgroundImage = null;
			this.contextMenu.Font = null;
			this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.refleshToolStripMenuItem,
            this.toolStripSeparator1,
            this.cutToolStripMenuItem,
            this.copyToolStripMenuItem,
            this.pasteToolStripMenuItem,
            this.toolStripSeparator2,
            this.newFolderToolStripMenuItem,
            this.newTxtTtoolStripMenuItem,
            this.toolStripSeparator3,
            this.renameToolStripMenuItem,
            this.toolStripSeparator4,
            this.deleteToolStripMenuItem});
			this.contextMenu.Name = "contextMenu";
			this.contextMenu.ShowImageMargin = false;
			this.contextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenu_Opening);
			// 
			// refleshToolStripMenuItem
			// 
			this.refleshToolStripMenuItem.AccessibleDescription = null;
			this.refleshToolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.refleshToolStripMenuItem, "refleshToolStripMenuItem");
			this.refleshToolStripMenuItem.BackgroundImage = null;
			this.refleshToolStripMenuItem.Name = "refleshToolStripMenuItem";
			this.refleshToolStripMenuItem.ShortcutKeyDisplayString = null;
			this.refleshToolStripMenuItem.Click += new System.EventHandler(this.refleshToolStripMenuItem_Click);
			// 
			// toolStripSeparator1
			// 
			this.toolStripSeparator1.AccessibleDescription = null;
			this.toolStripSeparator1.AccessibleName = null;
			resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1");
			this.toolStripSeparator1.Name = "toolStripSeparator1";
			// 
			// cutToolStripMenuItem
			// 
			this.cutToolStripMenuItem.AccessibleDescription = null;
			this.cutToolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.cutToolStripMenuItem, "cutToolStripMenuItem");
			this.cutToolStripMenuItem.BackgroundImage = null;
			this.cutToolStripMenuItem.Name = "cutToolStripMenuItem";
			this.cutToolStripMenuItem.ShortcutKeyDisplayString = null;
			this.cutToolStripMenuItem.Click += new System.EventHandler(this.cutToolStripMenuItem_Click);
			// 
			// copyToolStripMenuItem
			// 
			this.copyToolStripMenuItem.AccessibleDescription = null;
			this.copyToolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.copyToolStripMenuItem, "copyToolStripMenuItem");
			this.copyToolStripMenuItem.BackgroundImage = null;
			this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
			this.copyToolStripMenuItem.ShortcutKeyDisplayString = null;
			this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);
			// 
			// pasteToolStripMenuItem
			// 
			this.pasteToolStripMenuItem.AccessibleDescription = null;
			this.pasteToolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.pasteToolStripMenuItem, "pasteToolStripMenuItem");
			this.pasteToolStripMenuItem.BackgroundImage = null;
			this.pasteToolStripMenuItem.Name = "pasteToolStripMenuItem";
			this.pasteToolStripMenuItem.ShortcutKeyDisplayString = null;
			this.pasteToolStripMenuItem.Click += new System.EventHandler(this.pasteToolStripMenuItem_Click);
			// 
			// toolStripSeparator2
			// 
			this.toolStripSeparator2.AccessibleDescription = null;
			this.toolStripSeparator2.AccessibleName = null;
			resources.ApplyResources(this.toolStripSeparator2, "toolStripSeparator2");
			this.toolStripSeparator2.Name = "toolStripSeparator2";
			// 
			// newFolderToolStripMenuItem
			// 
			this.newFolderToolStripMenuItem.AccessibleDescription = null;
			this.newFolderToolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.newFolderToolStripMenuItem, "newFolderToolStripMenuItem");
			this.newFolderToolStripMenuItem.BackgroundImage = null;
			this.newFolderToolStripMenuItem.Name = "newFolderToolStripMenuItem";
			this.newFolderToolStripMenuItem.ShortcutKeyDisplayString = null;
			this.newFolderToolStripMenuItem.Click += new System.EventHandler(this.newFolderToolStripMenuItem_Click);
			// 
			// newTxtTtoolStripMenuItem
			// 
			this.newTxtTtoolStripMenuItem.AccessibleDescription = null;
			this.newTxtTtoolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.newTxtTtoolStripMenuItem, "newTxtTtoolStripMenuItem");
			this.newTxtTtoolStripMenuItem.BackgroundImage = null;
			this.newTxtTtoolStripMenuItem.Name = "newTxtTtoolStripMenuItem";
			this.newTxtTtoolStripMenuItem.ShortcutKeyDisplayString = null;
			this.newTxtTtoolStripMenuItem.Click += new System.EventHandler(this.newTxtTtoolStripMenuItem_Click);
			// 
			// toolStripSeparator3
			// 
			this.toolStripSeparator3.AccessibleDescription = null;
			this.toolStripSeparator3.AccessibleName = null;
			resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3");
			this.toolStripSeparator3.Name = "toolStripSeparator3";
			// 
			// renameToolStripMenuItem
			// 
			this.renameToolStripMenuItem.AccessibleDescription = null;
			this.renameToolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.renameToolStripMenuItem, "renameToolStripMenuItem");
			this.renameToolStripMenuItem.BackgroundImage = null;
			this.renameToolStripMenuItem.Name = "renameToolStripMenuItem";
			this.renameToolStripMenuItem.ShortcutKeyDisplayString = null;
			this.renameToolStripMenuItem.Click += new System.EventHandler(this.renameToolStripMenuItem_Click);
			// 
			// toolStripSeparator4
			// 
			this.toolStripSeparator4.AccessibleDescription = null;
			this.toolStripSeparator4.AccessibleName = null;
			resources.ApplyResources(this.toolStripSeparator4, "toolStripSeparator4");
			this.toolStripSeparator4.Name = "toolStripSeparator4";
			// 
			// deleteToolStripMenuItem
			// 
			this.deleteToolStripMenuItem.AccessibleDescription = null;
			this.deleteToolStripMenuItem.AccessibleName = null;
			resources.ApplyResources(this.deleteToolStripMenuItem, "deleteToolStripMenuItem");
			this.deleteToolStripMenuItem.BackgroundImage = null;
			this.deleteToolStripMenuItem.Name = "deleteToolStripMenuItem";
			this.deleteToolStripMenuItem.ShortcutKeyDisplayString = null;
			this.deleteToolStripMenuItem.Click += new System.EventHandler(this.deleteToolStripMenuItem_Click);
			// 
			// QView
			// 
			this.AccessibleDescription = null;
			this.AccessibleName = null;
			resources.ApplyResources(this, "$this");
			this.AllowColumnReorder = true;
			this.AllowDrop = true;
			this.BackgroundImage = null;
			this.BorderStyle = System.Windows.Forms.BorderStyle.None;
			this.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.chName,
            this.chSize,
            this.chType,
            this.chAttribute,
            this.chDateModify,
            this.chDateAccess,
            this.chDateCreate});
			this.LabelEdit = true;
			this.ShowItemToolTips = true;
			this.TileSize = new System.Drawing.Size(380, 120);
			this.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.QView_AfterLabelEdit);
			this.ItemMouseHover += new System.Windows.Forms.ListViewItemMouseHoverEventHandler(this.QView_ItemMouseHover);
			this.DoubleClick += new System.EventHandler(this.QView_DoubleClick);
			this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.QView_MouseUp);
			this.DragDrop += new System.Windows.Forms.DragEventHandler(this.QView_DragDrop);
			this.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.QView_ColumnClick);
			this.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.QView_ItemSelectionChanged);
			this.DragEnter += new System.Windows.Forms.DragEventHandler(this.QView_DragEnter);
			this.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.QView_ItemDrag);
			this.contextMenu.ResumeLayout(false);
			this.ResumeLayout(false);

		}

		#region Menu
		void newFolderToolStripMenuItem_Click(object sender, EventArgs e)
		{
			form.CreateFoloder();
		}

		void newTxtTtoolStripMenuItem_Click(object sender, EventArgs e)
		{
			string initName = "New Text Document";
			string txtname = initName + ".txt";
			try
			{
				int i;
				for (i = 1; i < 65536; )
				{
					if (File.Exists(Path.Combine(Pwd, txtname)))
					{
						txtname = initName + (++i).ToString() + ".txt";
					}
					else
					{
						string path = Path.Combine(Pwd, txtname);
						File.CreateText(path);
						break;
					}
				}
			}
			catch (System.Exception ex)
			{
				MessageBox.Show(ex.ToString());
			}
		}

		void renameToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (SelectedItems.Count == 0)
			{
				return;
			}
			ListViewItem item = SelectedItems[0];
			item.BeginEdit();
		}

		void deleteToolStripMenuItem_Click(object sender, EventArgs e)
		{
			foreach (ListViewItem item in SelectedItems)
			{
				if (Directory.Exists(item.Name))
				{
					Directory.Delete(item.Name, true);
				}
				else
				{
					File.Delete(item.Name);
				}
			}
		}

		private void cutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			CopyToClipboard(2);
		}

		void copyToolStripMenuItem_Click(object sender, EventArgs e)
		{
			CopyToClipboard(5);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="flag">2: cut; 5: copy</param>
		private void CopyToClipboard(int flag)
		{
			int n = SelectedItems.Count;
			if (n == 0)
			{
				return;
			}
			string[] files = new string[n];
			for (int i = 0; i < n; i++)
			{
				files[i] = SelectedItems[i].Name;
			}
			IDataObject data = new DataObject(DataFormats.FileDrop, files);
			MemoryStream memo = new MemoryStream(4);
			byte[] bytes = new byte[] { (byte)flag, 0, 0, 0 };
			memo.Write(bytes, 0, 4);
			data.SetData("Preferred DropEffect", memo);
			Clipboard.SetDataObject(data);
		}

		private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
		{
			IDataObject data = Clipboard.GetDataObject();
			if (!data.GetDataPresent(DataFormats.FileDrop))
			{
				return;
			}
			string[] files = (string[])data.GetData(DataFormats.FileDrop);
			MemoryStream memo = (MemoryStream)data.GetData("Preferred DropEffect", true);
			int flag = memo.ReadByte();
			if (flag != 2 && flag != 5)
			{
				return;
			}
			try
			{
				foreach (string path in files)
				{
					string newPath = Path.Combine(Pwd, Path.GetFileName(path));
					if (flag == 2)
					{
						Directory.Move(path, newPath);
					}
					else
					{
						CopyDir(path, newPath);
					}
				}
			}
			catch (IOException ex)
			{
				MessageBox.Show(ex.Message);
			}
			finally
			{
				Clipboard.Clear();
			}
		}

		private void CopyDir(string path, string newPath)
		{
			if (Directory.Exists(path))
			{
				Directory.CreateDirectory(newPath);
				foreach (string entry in Directory.GetFileSystemEntries(path))
				{
					string filename = Path.GetFileName(entry);
					CopyDir(Path.Combine(path, filename), Path.Combine(newPath, filename));
				}
			}
			else
			{
				File.Copy(path, newPath);
			}
		}

		private void refleshToolStripMenuItem_Click(object sender, EventArgs e)
		{
			form.Reflesh();
		}

		private void contextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
		{
			cutToolStripMenuItem.Enabled = SelectedItems.Count > 0;
			copyToolStripMenuItem.Enabled = SelectedItems.Count > 0;
			IDataObject data = Clipboard.GetDataObject();
			pasteToolStripMenuItem.Enabled = data.GetDataPresent(DataFormats.FileDrop);
			newFolderToolStripMenuItem.Enabled = SelectedItems.Count == 0;
			newTxtTtoolStripMenuItem.Enabled = SelectedItems.Count == 0;
			deleteToolStripMenuItem.Enabled = SelectedItems.Count > 0;
			renameToolStripMenuItem.Enabled = SelectedItems.Count > 0;
		}

		#endregion
		public void SetImageList(IntPtr large, IntPtr small)
		{
			API.SendMessage(Handle, API.LVM_SETIMAGELIST,
				(IntPtr)API.LVSIL_NORMAL, large);
			API.SendMessage(Handle, API.LVM_SETIMAGELIST,
				(IntPtr)API.LVSIL_SMALL, small);
		}

		private void QView_DoubleClick(object sender, EventArgs e)
		{
			if (SelectedItems.Count == 0)
			{
				return;
			}
			string path = SelectedItems[0].Name;
			form.Open(path);
		}

		private void QView_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left)
			{
				if (HitTest(e.X, e.Y).Item == null)
				{
					if (lastClickPosition == Cursor.Position
						&& Environment.TickCount - lastClickTick < SystemInformation.DoubleClickTime)
					{
						DirectoryInfo parent = Directory.GetParent(Pwd);
						if (parent != null)
						{
							OpenDir(parent.FullName);
							form.OnActiveView();
						}
					}
					lastClickTick = Environment.TickCount;
					lastClickPosition = Cursor.Position;
				}
			}
			else if (e.Button == MouseButtons.Right)
			{
				contextMenu.Show(this, e.Location);
			}

		}

		private void QView_ColumnClick(object sender, ColumnClickEventArgs e)
		{
			// 			lv.ListViewItemSorter = new ListViewComparer(e.Column);
			SetGroups(e.Column);
		}

		private void QView_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
		{
			e.Item.ToolTipText = Columns[2].Text + ": " + e.Item.SubItems[2].Text + Environment.NewLine
				+ Columns[4].Text + ": " + e.Item.SubItems[4].Text;
		}

		#region Drag & Drop
		private void QView_DragEnter(object sender, DragEventArgs e)
		{
			if ((e.KeyState & 8) == 8)	// Ctrl
			{
				e.Effect = DragDropEffects.Copy;
			}
			else
			{
				e.Effect = DragDropEffects.Move;
			}
		}

		private void QView_DragDrop(object sender, DragEventArgs e)
		{
			string path  = (string)e.Data.GetData(typeof(string));
			if (path == null)
			{
				return;
			}
			Point targetPoint = this.PointToClient(new Point(e.X, e.Y));
			ListViewItem targetItem = this.GetItemAt(targetPoint.X, targetPoint.Y);
			string newPath = Pwd;
			if (targetItem!=null)
			{
				if (targetItem.Name == path)
				{
					return;
				}
				newPath = Path.Combine(targetItem.Name, Path.GetFileName(path));
			} 
			
			try
			{
			if ((e.KeyState & 8) == 8)	// Ctrl
			{
				e.Effect = DragDropEffects.Copy;
				CopyDir(path, newPath);
			} 
			else if ((e.KeyState & 4) == 4)	// Shift
			{
				e.Effect = DragDropEffects.Move;
				Directory.Move(path, newPath);
			}
			else if (Path.GetPathRoot(path) == Path.GetPathRoot(newPath))
			{
				e.Effect = DragDropEffects.Move;
				Directory.Move(path, newPath);
			}
			else
			{
				e.Effect = DragDropEffects.Copy;
				CopyDir(path, newPath);
			}
			}
			catch (System.Exception ex)
			{
				MessageBox.Show(ex.Message, form.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void QView_ItemDrag(object sender, ItemDragEventArgs e)
		{
			ListViewItem item = (ListViewItem)e.Item;
			DoDragDrop(item.Name, DragDropEffects.Move | DragDropEffects.Copy | DragDropEffects.Link);
		}
		#endregion

		public void OpenDirInHistory(string dir)
		{
			Debug.WriteLine("Open folder: " + dir);
			numFiles = 0;
			numFolders = 0;
			numHidden = 0;
			string[] entries = Directory.GetFileSystemEntries(dir);
			Items.Clear();
			SHFILEINFO sfi = new SHFILEINFO();
			foreach (string path in entries)
			{
				if (form.CanShowFile(path))
				{
					FileInfo file = new FileInfo(path);
					AddItem(file, ref sfi);
				}
				else
				{
					numHidden++;
				}
			}

			if (ShowGroups)
			{
				SetGroups(sortColIndex);
			}
			Pwd = dir;
			TabPage tab = (TabPage)(Parent);
			tab.ToolTipText = dir;
			form.Status = String.Format(form.rm.GetString("StatusUnselected"),
				numFolders, numFiles, numHidden);
		}

		public void OpenDir(string dir)
		{
			bool refleshing = Pwd == dir;
			if (Pwd != null && !refleshing)
			{
				History.Insert(0, Pwd);
			}
			if (History.Count > HistoryCapacity)
			{
				History.RemoveRange(HistoryCapacity, History.Count - HistoryCapacity);
			}
			OpenDirInHistory(dir);
			if (!refleshing)
			{
				History.RemoveRange(0, PosInHistory);
				PosInHistory = 0;
			}
		}
		public void AddItem(string path)
		{
			SHFILEINFO sfi = new SHFILEINFO();
			AddItem(new FileInfo(path), ref sfi);
		}

		public void AddItem(FileInfo file, ref SHFILEINFO sfi)
		{
			// Add subitems
			ListViewItem item = new ListViewItem(file.Name);

			for (int i = 1; i < (int)Column.Count; i++)
			{
				item.SubItems.Add("");
			}
			item.Name = file.FullName;
			API.GetFileInfo(file.FullName, ref sfi,
				API.SHGFI_SYSICONINDEX | API.SHGFI_TYPENAME);
			item.ImageIndex = sfi.iIcon;
			try
			{
				if ((file.Attributes & FileAttributes.Directory) == 0)
				{
					numFiles++;
					item.SubItems[(int)Column.Size].Text = DisplaySize(file.Length);
					item.SubItems[(int)Column.Size].Tag = file.Length;
				}
				else
				{
					numFolders++;
					item.SubItems[(int)Column.Size].Text =
						Directory.GetDirectories(file.FullName).Length
						+ "/"
						+ Directory.GetFiles(file.FullName).Length;
				}
				item.SubItems[(int)Column.Type].Text = sfi.szTypeName;
				item.SubItems[(int)Column.Attribute].Text = DisplayAttribute(file.Attributes);
				item.SubItems[(int)Column.Attribute].Tag = file.Attributes;
				item.SubItems[(int)Column.ModifiedDate].Text = file.LastWriteTime.ToString();
				item.SubItems[(int)Column.ModifiedDate].Tag = file.LastWriteTime;
				item.SubItems[(int)Column.AccessDate].Text = file.LastAccessTime.ToString();
				item.SubItems[(int)Column.AccessDate].Tag = file.LastAccessTime;
				item.SubItems[(int)Column.CreationDate].Text = file.CreationTime.ToString();
				item.SubItems[(int)Column.CreationDate].Tag = file.CreationTime;
				FileColorFilter(file, item);
				if (Properties.Settings.Default.HideKnownExt)
				{
					if (IsknownType(file.Name, sfi.szTypeName))
					{
						API.GetFileInfo(file.FullName, ref sfi, API.SHGFI_DISPLAYNAME);
						item.Text = sfi.szDisplayName;
					}
				}
			}
			catch (System.Exception ex)
			{
				Debug.WriteLine(ex.ToString());
			}

			Items.Add(item);

		}

		private bool IsknownType(string filename, string typename)
		{
			string[] parts = typename.Split(' ');
			if (parts[parts.Length - 1] == "文件")
			{
				if (parts.Length == 1)
				{
					return false;
				}
				if (parts.Length == 2)
				{
					if ("." + parts[0] == Path.GetExtension(filename))
					{
						return false;
					}
				}
			}
			return true;
		}

		private void FileColorFilter(FileInfo file, ListViewItem item)
		{
			if ((file.Attributes & FileAttributes.System) != 0)
			{
				item.ForeColor = Color.Blue;
			}
			else
			{
			}
		}

		private void SetGroups(int column)
		{
			Hashtable groups = new Hashtable();
			Groups.Clear();
			switch (column)
			{
			case (int)Column.Name:
				foreach (ListViewItem item in Items)
				{
					string groupHeader = item.SubItems[column].Text.Substring(0, 1).ToUpper();
					bool bGroupExsit = false;
					foreach (ListViewGroup group in Groups)
					{
						if (group.Header == groupHeader)
						{
							bGroupExsit = true;
							item.Group = group;
							break;
						}
					}
					if (!bGroupExsit)
					{
						ListViewGroup newgroup = new ListViewGroup(groupHeader);
						Groups.Add(newgroup);
						item.Group = newgroup;
					}
				}
				break;
			case (int)Column.Size:
				const int SMALLL_FILE = 1024 * 100;
				const int MID_FILE = SMALLL_FILE * 100;
				const int LARGE_FILE = MID_FILE * 100;
				Groups.Add("Small", "Small");
				Groups.Add("Middle", "Middle");
				Groups.Add("Large", "Large");
				Groups.Add("Huge", "Huge");
				Groups.Add("Folder", "Folder");
				foreach (ListViewItem item in Items)
				{
					if (((FileAttributes)(item.SubItems[(int)Column.Attribute].Tag) & FileAttributes.Directory) != 0)
					{
						item.Group = Groups[4];
						continue;
					}
					int size = Convert.ToInt32(item.SubItems[column].Tag);
					if (size < SMALLL_FILE)
					{
						item.Group = Groups[0];
					}
					else if (size < MID_FILE)
					{
						item.Group = Groups[1];
					}
					else if (size < LARGE_FILE)
					{
						item.Group = Groups[2];
					}
					else
					{
						item.Group = Groups[3];
					}
				}
				break;
			case (int)Column.ModifiedDate:
			case (int)Column.AccessDate:
			case (int)Column.CreationDate:
				Groups.Add("Today", "Today");
				Groups.Add("Earlier this week", "Earlier this week");
				Groups.Add("Earlier this month", "Earlier this month");
				Groups.Add("this year", "this year");
				Groups.Add("Long time ago", "Long time ago");
				foreach (ListViewItem item in Items)
				{
					DateTime date = (DateTime)(item.SubItems[column].Tag);
					DateTime today = DateTime.Today;
					if (date.Date == today)
					{
						item.Group = Groups[0];
					}
					else if (today - date < TimeSpan.FromDays((double)(today.DayOfWeek)))
					{
						item.Group = Groups[1];
					}
					else if (date.Month == DateTime.Today.Month)
					{
						item.Group = Groups[2];
					}
					else if (date.Year == DateTime.Today.Year)
					{
						item.Group = Groups[3];
					}
					else
					{
						item.Group = Groups[4];
					}
				}
				break;
			default:
				foreach (ListViewItem item in Items)
				{
					string groupHeader = item.SubItems[column].Text;
					bool bGroupExsit = false;
					foreach (ListViewGroup group in Groups)
					{
						if (group.Header == groupHeader)
						{
							bGroupExsit = true;
							item.Group = group;
							break;
						}
					}
					if (!bGroupExsit)
					{
						ListViewGroup newgroup = new ListViewGroup(groupHeader);
						Groups.Add(newgroup);
						item.Group = newgroup;
					}
				}
				break;
			}
		}

		private string DisplaySize(long length)
		{
			Double d = Convert.ToDouble(length);
			if (d < 1024)
			{
				return d.ToString() + " Bytes";
			}
			else if (d < 1024 * 1024)
			{
				return (d / 1024).ToString("G3") + " KB";
			}
			else if (d < 1024L * 1024L * 1024L)
			{
				return (d / 1024 / 1024).ToString("G3") + " MB";
			}
			else
			{
				return (d / 1024 / 1024 / 1024).ToString("G3") + " GB";
			}
		}

		private string DisplayAttribute(FileAttributes attr)
		{
			string r = "";
			r += ((attr & FileAttributes.Archive) != 0) ? "A" : "";
			r += ((attr & FileAttributes.Compressed) != 0) ? "C" : "";
			r += ((attr & FileAttributes.Encrypted) != 0) ? "E" : "";
			r += ((attr & FileAttributes.ReadOnly) != 0) ? "R" : "";
			r += ((attr & FileAttributes.System) != 0) ? "S" : "";
			return r;
		}

		private void QView_AfterLabelEdit(object sender, LabelEditEventArgs e)
		{
			ListViewItem it = Items[e.Item];
			try
			{
				form.WatcherEnabled = false;
				FileInfo file = new FileInfo(it.Name);
				if ((file.Attributes & FileAttributes.Directory) != 0)
				{
					Directory.Move(it.Name, Path.Combine(Pwd, e.Label));
				}
				else
				{
					File.Move(Items[e.Item].Name,
						Path.Combine(Pwd, e.Label) + Path.GetExtension(Items[e.Item].Name));
				}
				form.WatcherEnabled = true;
			}
			catch (System.Exception ex)
			{
				e.CancelEdit = true;
				MessageBox.Show(ex.Message);
			}
		}

		private void QView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
		{
			if (SelectedItems.Count>0)
			{
				form.Status = string.Format(form.rm.GetString("StatusSelected"), SelectedItems.Count);
			} 
			else
			{
				form.Status = String.Format(form.rm.GetString("StatusUnselected"),
					numFolders, numFiles, numHidden);
			}
		}
	}

}

